#include "h264_source.h"

using namespace VLRTSP;

/**
 * @Author: CimZzz
 * @Date: 2022-01-13 16:17:58
 * 
 * 构造函数
 */
H264Source::H264Source(): MediaSource() {
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-13 16:18:03
 * 
 * 析构函数
 */
H264Source::~H264Source() {

}


/**
 * @Author: CimZzz
 * @Date: 2022-01-13 16:49:32
 * 
 * 构建媒体资源 SDP 段
 * @param buffer 字节缓冲区
 */
void H264Source::buildSourceSDP(Buffer* buffer) {
	buffer->appendPrint(
		"m=video 0 RTP/AVP 96\r\n"
		"a=rtpmap:96 H264/90000\r\n"
        "a=framerate:25\r\n"
	);
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-14 14:18:33
 * 
 * 处理数据缓冲，组装成 RTP 帧，通过 [sendRTPFrame] 进行发送
 * @param data 外部传来的数据
 */
void H264Source::onHandleDataBuffer(std::shared_ptr<MediaSourceData>& data) {
	MediaSourceData* dataPtr = data.get();
	Buffer* buffer = dataPtr->buffer.get();
	uint32_t frameSize = buffer->getBufferLength();
	if(frameSize <= MAX_RTP_PAYLOAD_LENGTH) {
		std::shared_ptr<RTPFrame> rtpFrame(new RTPFrame);
		RTPFrame* framePtr = rtpFrame.get();
		Buffer* frameBuffer = framePtr->buffer.get();
		this->fillRTPHeader(frameBuffer, dataPtr->timestamp);
		frameBuffer->appendBuffer(buffer);
		this->sendRTPFrame(rtpFrame);
	} else {

		uint8_t FU_A[2] = {0};
        FU_A[0] = (buffer->getBuffer()[0] & 0xE0) | 28;
        FU_A[1] = 0x80 | (buffer->getBuffer()[0] & 0x1f);
		uint32_t bufferOffset = 0;
		frameSize -= 1;

		// 分片
		while(frameSize + 2 > MAX_RTP_PAYLOAD_LENGTH) {
			std::shared_ptr<RTPFrame> rtpFrame(new RTPFrame);
			RTPFrame* framePtr = rtpFrame.get();
			Buffer* frameBuffer = framePtr->buffer.get();
			this->fillRTPHeader(frameBuffer, dataPtr->timestamp, false);
			frameBuffer->appendBuffer(FU_A, 0, 2);
			frameBuffer->appendBuffer(buffer, bufferOffset, MAX_RTP_PAYLOAD_LENGTH - 2);
			this->sendRTPFrame(rtpFrame);
			
			bufferOffset += MAX_RTP_PAYLOAD_LENGTH - 2;
			frameSize -= MAX_RTP_PAYLOAD_LENGTH - 2;
			FU_A[1] &= ~0x80;
		}
		std::shared_ptr<RTPFrame> rtpFrame(new RTPFrame);
		RTPFrame* framePtr = rtpFrame.get();
		Buffer* frameBuffer = framePtr->buffer.get();
		this->fillRTPHeader(frameBuffer, dataPtr->timestamp);
		FU_A[1] |= 0x40;
		frameBuffer->appendBuffer(FU_A, 0, 2);
		frameBuffer->appendBuffer(buffer, bufferOffset, frameSize);
		this->sendRTPFrame(rtpFrame);
	}
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-10 15:57:04
 * 
 * 获取载荷类型
 * @return 返回载荷类型，参照 [PayloadType] 枚举
 */
PayloadType H264Source::getPayloadType() const {
	return SourceType_H264;
}